/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ngramassigment.fileprocess;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import ngramassigment.Config;
import ngramassigment.Utils;
import ngramassigment.database.DatabaseManager;

/**
 *
 * @author Tran
 */
public class FileFunction {

    private HashMap<String, Integer> hmId = new HashMap<String, Integer>();
    private HashMap<String, Integer> hmCounter = new HashMap<String, Integer>();
    private List<HashMap<Double, Integer>> lsCounterGram = new ArrayList<HashMap<Double, Integer>>();
    private int maxValueBefore;
    private static FileFunction instance = null;

    public static FileFunction getInstance() {
        if (instance == null) {
            instance = new FileFunction();
        }
        return instance;
    }

    public FileFunction() {

        //init hashMap for nGram counter
        for (int i = 0; i < Config.MAX_NUM_TYPE_GRAM; i++) {
            HashMap<Double, Integer> hmCounterGram = new HashMap<Double, Integer>();
            lsCounterGram.add(hmCounterGram);
        }
        maxValueBefore = 0;
        try {
            maxValueBefore = Utils.getMaxValue(Config.PROP_KEY_MAX_VALUE);
            //add all to hashMap
        } catch (IOException ex) {
            //Logger.getLogger(FileFunction.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //process file which contain all single phrase
    public void processOneFileSeparate(String fileName, int currentFile) throws FileNotFoundException, IOException {
        // Open the file
        FileInputStream fstream = new FileInputStream(fileName);
        BufferedReader br = new BufferedReader(new InputStreamReader(fstream));

        if (!Config.IS_UPDATE_DICTIONARY) {
            maxValueBefore = 0;
        }
        String strLine;
        //Read File Line By Line
        while ((strLine = br.readLine()) != null) {
            // Print the content on the console
            processOneLineFileSeparate(strLine, currentFile);
        }
        br.close();
    }

    private List<String> splitSignleWord(String[] lsWord) {
        List<String> lsWordFilter = new ArrayList<String>();
        PrintWriter outDic = null;
        try {
            outDic = new PrintWriter(new BufferedWriter(new FileWriter(Config.PATH_DATA_DICTIONARY, true)));
            for (int i = 0; i < lsWord.length; i++) {
                if (lsWord[i].trim().length() >= 1) {
                    processUpdateHashmapVocabulary(lsWord[i].trim(), outDic);
                    lsWordFilter.add(lsWord[i].trim().toUpperCase());
                }
            }
        } catch (IOException e) {
            //System.err.println(e);
        } finally {
            if (outDic != null) {
                outDic.close();
            }
        }
        return lsWordFilter;
    }

    private void processOneLineFileSeparate(String strLine, int currentFile) {
        String[] lsWord = strLine.trim().split("\\s+");
        List<String> lsWordFilter = new ArrayList<String>();

        lsWordFilter = splitSignleWord(lsWord);

        PrintWriter outNu = null;
        PrintWriter outWo = null;
        for (int i = 0; i < Config.MAX_NUM_TYPE_GRAM; i++) {
            try {
                outNu = new PrintWriter(new BufferedWriter(new FileWriter(Config.PATH_ALL_BI_GRAM_NUM + (i + 2) + "_GRAM" + currentFile + ".txt", true)));
                outWo = new PrintWriter(new BufferedWriter(new FileWriter(Config.PATH_ALL_BI_GRAM_WORD + (i + 2) + "_GRAM" + currentFile + ".txt", true)));
                processUpdateGram(lsWordFilter, outNu, outWo, i + 2);
            } catch (IOException e) {
                //System.err.println(e);
            } finally {
                if (outNu != null) {
                    outNu.close();
                }
                if (outWo != null) {
                    outWo.close();
                }
            }
        }

    }

    private void processUpdateHashmapVocabulary(String word, PrintWriter outDic) {
        word = word.toUpperCase();
        if (!hmId.containsKey(word)) {
            maxValueBefore++;
            hmId.put(word, maxValueBefore);
            hmCounter.put(word, 1);
            if (Config.IS_UPDATE_DICTIONARY) {
                outDic.println(word + "\t\t" + maxValueBefore);
            }
        } else {
            int current = (int) hmCounter.get(word);
            hmCounter.put(word, current + 1);  // update value of counter for this word
        }
    }

    public void storeDataInHashMapToDatabase() {
        //update vocabulary
        DatabaseManager.getInstance().updateDataOfVocabulary(hmId, hmCounter);
        //update nGram
        for (int i=0; i<Config.MAX_NUM_TYPE_GRAM; i++) {
            DatabaseManager.getInstance().updateDataNGram(lsCounterGram.get(i), i+2);
        }
        Utils.storeMaxValue(Config.PROP_KEY_MAX_VALUE, maxValueBefore);
    }

    public void storeMaxValue2Prop() {
        Utils.storeMaxValue(Config.PROP_KEY_MAX_VALUE, maxValueBefore);
    }

//    public void loadDatabaseVocabularyToHashMap() throws SQLException {
//        ResultSet rs = DatabaseManager.getInstance().selectAllDataOfVocabulary();
//        while (rs.next()) {
//            int id = rs.getInt(DatabaseConfig.TB_VOCA_FIELD_ID);
//            String word = rs.getString(DatabaseConfig.TB_VOCA_FIELD_WORD);
//            int count = rs.getInt(DatabaseConfig.TB_VOCA_FIELD_COUNT);
//            hmId.put(word, id);
//            hmCounter.put(word, count);
//        }
//        rs.close();
//    }

    private void processUpdateGram(List<String> lsWordFilter, PrintWriter outNum, PrintWriter outWo, int typeGram) {
        for (int i = 0; i < lsWordFilter.size() - (typeGram - 1); i++) {
            String writeNum;
            String writeWord;
            double  calculateIndex = 0;
            for (int j = 0; j < typeGram; j++) {
                outNum.print((int) hmId.get(lsWordFilter.get(i + j)) + " ");
                outWo.print(lsWordFilter.get(i + j) + " ");
                calculateIndex += ((double) hmId.get(lsWordFilter.get(i + j))) * ((double) Math.pow(Config.MAX_WORD, typeGram - j - 1));
            }
            HashMap<Double, Integer> hmTemp = lsCounterGram.get(typeGram - 2);
            if (!hmTemp.containsKey(calculateIndex)) {                
                hmTemp.put(calculateIndex, 1);              
               
            } else {
                int current = (int) hmTemp.get(calculateIndex);
                hmTemp.put(calculateIndex, current + 1);  // update value of counter for this word
            }            
            outNum.println();
            outWo.println();
        }
    }
    
    
}
